#include <glib.h>
#include <pthread.h>

typedef int (*foobar_method)(gint a, gint b);

typedef struct foobar_tag {
    gint foo;
    gint bar;
    foobar_method func; 
}foobar_t;

static gint test_foobar_add(gint a, gint b)
{
    return a + b;
}

static gint test_foobar_multi(gint a, gint b)
{
    return a * b;
}

static void test_thread_pool_func(gpointer data, gpointer user_data)
{
    gint ret_val = 0;
    foobar_t *foobar = NULL;

    foobar = (foobar_t *)data;
    if(NULL == foobar) {
        g_print("input param is NULL \n");
        return;
    }

    ret_val = foobar->func(foobar->foo, foobar->bar);
    g_print("ret_val: %d \n", ret_val);

    g_free(foobar);
}

gpointer test_thread_func(gpointer data)
{
    foobar_t *foobar1 = NULL;
    foobar_t *foobar2 = NULL;
    GThreadPool *pool = (GThreadPool *)data;

    foobar1 = g_new0(foobar_t, 1);
    foobar1->foo = 2;
    foobar1->bar = 3;
    foobar1->func = test_foobar_add;
    g_thread_pool_push(pool, foobar1, NULL);

    foobar2 = g_new0(foobar_t, 1);
    foobar2->foo = 2;
    foobar2->bar = 3;
    foobar2->func = test_foobar_multi;
    g_thread_pool_push(pool, foobar2, NULL);

    return NULL;
}

void test_thread_pool(void)
{
    guint num = 0;
    GError *error = NULL;
    gint max_threads = 4;
    GThreadPool *pool = NULL;
    GThread *thd = NULL;

    pool = g_thread_pool_new(test_thread_pool_func, NULL, max_threads, TRUE, &error);

    thd = g_thread_new("thd", test_thread_func, pool);
    g_usleep(100*1000);
    g_thread_join(thd);

    g_thread_pool_free(pool, TRUE, TRUE);
}

gint main(gint argc, gchar **argv)
{
    test_thread_pool();
}